package cn.iocoder.yudao.module.lowcode.controller.admin.script;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.lowcode.controller.admin.script.vo.*;
import cn.iocoder.yudao.module.lowcode.core.script.GroovyScriptExecutionContext;
import cn.iocoder.yudao.module.lowcode.core.service.GroovyScriptService;
import cn.iocoder.yudao.module.lowcode.dal.dataobject.script.GroovyScriptDO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - Groovy 脚本")
@RestController
@RequestMapping("/lowcode/groovy/script")
@Validated
public class GroovyScriptController {

    @Resource
    private GroovyScriptService groovyScriptService;

    @PostMapping("/create")
    @Operation(summary = "创建 Groovy 脚本")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:create')")
    public CommonResult<Long> createGroovyScript(@Valid @RequestBody GroovyScriptCreateReqVO createReqVO) {
        return success(groovyScriptService.createGroovyScript(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新 Groovy 脚本")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:update')")
    public CommonResult<Boolean> updateGroovyScript(@Valid @RequestBody GroovyScriptUpdateReqVO updateReqVO) {
        groovyScriptService.updateGroovyScript(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除 Groovy 脚本")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:delete')")
    public CommonResult<Boolean> deleteGroovyScript(@RequestParam("id") Long id) {
        groovyScriptService.deleteGroovyScript(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得 Groovy 脚本")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<GroovyScriptRespVO> getGroovyScript(@RequestParam("id") Long id) {
        GroovyScriptDO groovyScript = groovyScriptService.getGroovyScript(id);
        return success(BeanUtils.toBean(groovyScript, GroovyScriptRespVO.class));
    }

    @GetMapping("/list")
    @Operation(summary = "获得 Groovy 脚本列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<List<GroovyScriptRespVO>> getGroovyScriptList(@RequestParam("ids") Collection<Long> ids) {
        List<GroovyScriptDO> list = groovyScriptService.getGroovyScriptList(ids);
        return success(BeanUtils.toBean(list, GroovyScriptRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得 Groovy 脚本分页")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<PageResult<GroovyScriptRespVO>> getGroovyScriptPage(@Valid GroovyScriptPageReqVO pageVO) {
        PageResult<GroovyScriptDO> pageResult = groovyScriptService.getGroovyScriptPage(pageVO);
        return success(BeanUtils.toBean(pageResult, GroovyScriptRespVO.class));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出 Groovy 脚本 Excel")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:export')")
    public void exportGroovyScriptExcel(@Valid GroovyScriptPageReqVO pageVO,
              HttpServletResponse response) throws IOException {
        pageVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<GroovyScriptDO> list = groovyScriptService.getGroovyScriptPage(pageVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "Groovy 脚本.xls", "数据", GroovyScriptRespVO.class,
                        BeanUtils.toBean(list, GroovyScriptRespVO.class));
    }

    @GetMapping("/get-by-name")
    @Operation(summary = "根据脚本名称获取脚本")
    @Parameter(name = "scriptName", description = "脚本名称", required = true)
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<GroovyScriptRespVO> getGroovyScriptByName(@RequestParam("scriptName") String scriptName) {
        GroovyScriptDO groovyScript = groovyScriptService.getGroovyScriptByName(scriptName);
        return success(BeanUtils.toBean(groovyScript, GroovyScriptRespVO.class));
    }

    @GetMapping("/list-by-category")
    @Operation(summary = "根据分类获取脚本列表")
    @Parameter(name = "category", description = "分类", required = true)
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<List<GroovyScriptRespVO>> getGroovyScriptsByCategory(@RequestParam("category") String category) {
        List<GroovyScriptDO> list = groovyScriptService.getGroovyScriptsByCategory(category);
        return success(BeanUtils.toBean(list, GroovyScriptRespVO.class));
    }

    @GetMapping("/list-active")
    @Operation(summary = "获取活跃脚本列表")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<List<GroovyScriptRespVO>> getActiveGroovyScripts() {
        List<GroovyScriptDO> list = groovyScriptService.getActiveGroovyScripts();
        return success(BeanUtils.toBean(list, GroovyScriptRespVO.class));
    }

    @PostMapping("/execute")
    @Operation(summary = "执行 Groovy 脚本")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:execute')")
    public CommonResult<Object> executeScript(@Valid @RequestBody GroovyScriptExecuteReqVO executeReqVO) {
        // 构建执行上下文
        GroovyScriptExecutionContext context = GroovyScriptExecutionContext.builder()
                .parameters(executeReqVO.getParameters())
                .build();
        
        // 执行脚本
        Object result = groovyScriptService.executeScript(executeReqVO.getScriptName(), context);
        return success(result);
    }

    @PostMapping("/validate")
    @Operation(summary = "验证 Groovy 脚本语法")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:validate')")
    public CommonResult<GroovyScriptValidationRespVO> validateScript(@Valid @RequestBody GroovyScriptValidateReqVO validateReqVO) {
        GroovyScriptService.ScriptValidationResult result = groovyScriptService.validateScript(validateReqVO.getScriptContent());
        
        GroovyScriptValidationRespVO respVO = new GroovyScriptValidationRespVO();
        respVO.setValid(result.isValid());
        respVO.setErrorMessage(result.getErrorMessage());
        respVO.setWarnings(result.getWarnings());
        
        return success(respVO);
    }

    @PostMapping("/test")
    @Operation(summary = "测试 Groovy 脚本执行")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:test')")
    public CommonResult<Object> testScript(@Valid @RequestBody GroovyScriptTestReqVO testReqVO) {
        // 构建测试上下文
        GroovyScriptExecutionContext context = GroovyScriptExecutionContext.builder()
                .parameters(testReqVO.getParameters())
                .build();
        
        // 测试脚本
        Object result = groovyScriptService.testScript(testReqVO.getScriptContent(), context);
        return success(result);
    }

    @PostMapping("/execute-code")
    @Operation(summary = "直接执行 Groovy 代码（用于测试）")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:execute')")
    public CommonResult<Object> executeCode(@Valid @RequestBody GroovyScriptTestReqVO testReqVO) {
        // 构建执行上下文
        GroovyScriptExecutionContext context = GroovyScriptExecutionContext.builder()
                .parameters(testReqVO.getParameters())
                .build();
        
        // 直接执行代码
        Object result = groovyScriptService.testScript(testReqVO.getScriptContent(), context);
        return success(result);
    }

    @GetMapping("/cache-info")
    @Operation(summary = "获取脚本缓存信息")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<Object> getScriptCacheInfo() {
        // TODO: 实现缓存信息获取
        return success("缓存信息功能待实现");
    }

    @PostMapping("/clear-cache")
    @Operation(summary = "清除脚本缓存")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:cache')")
    public CommonResult<Boolean> clearScriptCache(@RequestBody(required = false) String name) {
        if (name != null) {
            groovyScriptService.evictScriptCache(name);
        } else {
            groovyScriptService.evictAllScriptCache();
        }
        return success(true);
    }

    @PostMapping("/preload-cache")
    @Operation(summary = "预热脚本缓存")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:cache')")
    public CommonResult<Boolean> preloadScriptCache() {
        // TODO: 实现缓存预热
        return success(true);
    }

    @GetMapping("/version-history")
    @Operation(summary = "获取脚本版本历史")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<Object> getScriptVersionHistory(@RequestParam("scriptId") Long scriptId) {
        // TODO: 实现版本历史功能
        return success("版本历史功能待实现");
    }

    @PostMapping("/rollback")
    @Operation(summary = "回滚到指定版本")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:update')")
    public CommonResult<Boolean> rollbackScriptVersion(@RequestBody Object data) {
        // TODO: 实现版本回滚功能
        return success(true);
    }

    @PutMapping("/update-status")
    @Operation(summary = "修改脚本状态")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:update')")
    public CommonResult<Boolean> updateScriptStatus(@RequestBody Object data) {
        // TODO: 实现状态更新功能
        return success(true);
    }

    @GetMapping("/categories")
    @Operation(summary = "获取脚本分类列表")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:query')")
    public CommonResult<List<String>> getScriptCategories() {
        return success(Arrays.asList("data", "business", "util", "job", "api", "other"));
    }

    @PostMapping("/evict-cache")
    @Operation(summary = "清除脚本缓存")
    @Parameter(name = "scriptName", description = "脚本名称")
    @PreAuthorize("@ss.hasPermission('lowcode:groovy:cache')")
    public CommonResult<Boolean> evictScriptCache(@RequestParam(value = "scriptName", required = false) String scriptName) {
        if (scriptName != null) {
            groovyScriptService.evictScriptCache(scriptName);
        } else {
            groovyScriptService.evictAllScriptCache();
        }
        return success(true);
    }

    @GetMapping("/test")
    @Operation(summary = "测试端点")
    public CommonResult<String> test() {
        return success("Groovy Script Controller is working!");
    }
}